package org.bookie.framework.services.impl;

import javax.mail.MessagingException;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.tapestry.engine.ExternalServiceParameter;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.bookie.core.services.IUserManager;
import org.bookie.framework.services.EmailEngine;
import org.bookie.model.Role;
import org.bookie.model.User;
import org.bookie.model.services.UserDAO;

/**
 * Implementation of the user manager
 * 
 * @author zubairov
 * 
 */
public class UserManagerImpl implements IUserManager {

	private Log log;

	private UserDAO userDAO;

	private IEngineService externalService;
	
	private EmailEngine emailEngine;
	
	/**
	 * Registeres new user, send confirmation email, etc
	 * @param sendEmail 
	 * 
	 * @return true if user can be registered (user with given email do not
	 *         exists)
	 * @throws MessagingException 
	 */
	public RegistrationResult registerNewUser(User user, boolean sendEmail) throws MessagingException {
		if (userDAO.findByEmail(user.getEmail()) != null) {
			log.warn("User with email " + user.getEmail()
					+ " already exists, rejecting registration request");
			return RegistrationResult.DUPLICATE_EMAIL;
		}
		if (userDAO.findByUserName(user.getUsername()) != null) {
			log.warn("User with username " + user.getUsername()
					+ " already exists, rejecting registration request");
			return RegistrationResult.DUPLICATE_USERNAME;
		}
		
		String key = user.resetActivationKey();

		ILink link = externalService.getLink(false,
				new ExternalServiceParameter("Activation",
						new Object[] { key }));

		
		String url = link.getAbsoluteURL();
		
		// If everything was ok then store user and activation
		userDAO.makePersistent(user);	
		
		if (sendEmail) {
			emailEngine.sendEmail(user.getEmail(), "Registration",
					new Object[]{user.getUsername(), user.getEmail(), url});
		} else {
			user.setRole(Role.USER);
		}
		return RegistrationResult.OK;
	}
	

	/**
	 * {@inheritDoc}
	 */
	public RegistrationResult registerNewUser(User user) throws MessagingException {
		return registerNewUser(user, true);
	}
	
	/**
	 * Recreate password and resend it to user via email
	 * @throws MessagingException 
	 * @see IUserManager#recreatePassword(String, String)
	 */
	public boolean recreatePassword(String username, String email) throws MessagingException {
		if (username == null || email == null) {
			log.error("Username and email should not be null");
			return false;
		}
		User user = userDAO.findByEmail(email);
		if (username == null) {
			log.error("Username parameter should not be null");
			return false;
		}
		if (user == null) {
			log.debug("Can't find user with email " + email + ", password recreation failed");
			return false;
		}
		if (!username.equals(user.getUsername())) {
			log.debug("Passed username " + username + " do not match email " + email + " email");
			return false;
		}
		String newPassword = RandomStringUtils.random(8, true, true);
		user.setPassword(newPassword);
		userDAO.makePersistent(user);
		emailEngine.sendEmail(user.getEmail(), "Password",
				new Object[]{user.getUsername(), newPassword});
		return true;
	}

	/**
	 * Injected
	 * 
	 * @param log
	 */
	public void setLog(Log log) {
		this.log = log;
	}

	/**
	 * Injected
	 * 
	 * @param userDAO
	 */
	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}

	/**
	 * Injected service tapestry.services.External
	 * 
	 * @param externalService
	 */
	public void setExternalService(IEngineService externalService) {
		this.externalService = externalService;
	}
	
	/**
	 * Setter for {@link EmailEngine}
	 * @category injector
	 * @param emailEngine engine to set
	 */
	public void setEmailEngine(EmailEngine emailEngine) {
		this.emailEngine = emailEngine;
	}
}
